package com.bloom.web.controller.system;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import com.alibaba.fastjson.JSONObject;
import com.bloom.common.constant.Constants;
import com.bloom.common.constant.HttpStatus;
import com.bloom.common.core.domain.entity.SysUser;
import com.bloom.common.exception.CustomException;
import com.bloom.common.utils.AuthUtils;
import com.bloom.common.utils.SecurityUtils;
import com.bloom.common.utils.ServletUtils;
import com.bloom.common.utils.StringUtils;
import com.bloom.framework.web.service.SysLoginService;
import me.zhyd.oauth.cache.AuthDefaultStateCache;
import me.zhyd.oauth.cache.AuthStateCache;
import me.zhyd.oauth.model.AuthCallback;
import me.zhyd.oauth.model.AuthResponse;
import me.zhyd.oauth.model.AuthUser;
import me.zhyd.oauth.request.AuthRequest;
import me.zhyd.oauth.utils.AuthStateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.bloom.common.core.controller.BaseController;
import com.bloom.common.core.domain.AjaxResult;
import com.bloom.system.domain.SysAuthUser;
import com.bloom.system.service.ISysAuthUserService;

import javax.servlet.http.HttpServletRequest;

/**
 * 第三方授权Controller
 * 
 * @author bloom
 * @date 2021-05-11
 */
@RestController
@RequestMapping("/system/authUser")
public class SysAuthUserController extends BaseController
{
    private AuthStateCache authStateCache;

    @Autowired
    private SysLoginService loginService;

    @Autowired
    private ISysAuthUserService sysAuthUserService;

    private final static Map<String, String> auths = new HashMap<String, String>();
    {
        auths.put("gitee", "{\"clientId\":\"17de53136fed79ff265604dbfb97a0c2f6d7064aa3fed3dabaace7a82a4a8b53\",\"clientSecret\":\"93d5fd511c24bef156a2e18a870b85f22ef1e1d774d41fb4ff4b73bfa65a2aa9\",\"redirectUri\":\"http://bloom.free.idcfengye.com/system/authUser/auth/callback/gitee\"}");
        auths.put("github", "{\"clientId\":\"Iv1.1be0cdcd71aca63b\",\"clientSecret\":\"0d59d28b43152bc8906011624db37b0fed88d154\",\"redirectUri\":\"http://127.0.0.1:8080/system/authUser/auth/callback/github\"}");
        authStateCache = AuthDefaultStateCache.INSTANCE;
    }

    /**
     * 认证授权
     *
     * @param source
     * @throws IOException
     */
    @GetMapping("/auth/{source}")
    public AjaxResult renderAuth(@PathVariable("source") String source) throws IOException
    {
        String obj = auths.get(source);
        if (StringUtils.isEmpty(obj))
        {
            return AjaxResult.error("配置出现问题，请联系网络管理员！");
        }
        JSONObject json = JSONObject.parseObject(obj);
        AuthRequest authRequest = AuthUtils.getAuthRequest(source, json.getString("clientId"), json.getString("clientSecret"), json.getString("redirectUri"), authStateCache);
        String authorizeUrl = authRequest.authorize(AuthStateUtils.createState());
        return new AjaxResult(HttpStatus.SEE_OTHER, authorizeUrl);
    }

    /**
     * 回调结果
     */
    @SuppressWarnings("unchecked")
    @GetMapping("/auth/callback/{source}")
    public AjaxResult callbackAuth(@PathVariable("source") String source, AuthCallback callback, HttpServletRequest request)
    {
        AjaxResult ajax;
        String obj = auths.get(source);
        if (StringUtils.isEmpty(obj))
        {
            throw new CustomException("获取用户账户异常", HttpStatus.UNAUTHORIZED);
        }

        JSONObject json = JSONObject.parseObject(obj);
        AuthRequest authRequest = AuthUtils.getAuthRequest(source, json.getString("clientId"), json.getString("clientSecret"), json.getString("redirectUri"), authStateCache);
        AuthResponse<AuthUser> response = authRequest.login(callback);
        if (response.ok())
        {
            if (SecurityUtils.getAuthentication() != null && SecurityUtils.getAuthentication().getPrincipal() != null)
            {
                SysUser user = sysAuthUserService.selectAuthUserByUuid(source + response.getData().getUuid());
                if (StringUtils.isNotNull(user))
                {
                    ajax = new AjaxResult(HttpStatus.SEE_OTHER, "/index");
                    return ajax;
                }
                // 若已经登录则直接绑定系统账号
                SysAuthUser authUser = new SysAuthUser();
                authUser.setAvatar(response.getData().getAvatar());
                authUser.setUuid(source + response.getData().getUuid());
                authUser.setUserId(SecurityUtils.getLoginUser().getUser().getUserId());
                authUser.setUserName(response.getData().getNickname());
                authUser.setLoginName(response.getData().getUsername());
                authUser.setEmail(response.getData().getEmail());
                authUser.setSource(source);
                sysAuthUserService.insertSysAuthUser(authUser);
                ajax = new AjaxResult(HttpStatus.SEE_OTHER, "/index");
                return ajax;
            }
            SysUser user = sysAuthUserService.selectAuthUserByUuid(source + response.getData().getUuid());
            if (StringUtils.isNotNull(user))
            {
                ajax = AjaxResult.success();
                String token = loginService.login(user.getUserName(), user.getPassword(), "no");
                ajax.put(Constants.TOKEN, token);
                return ajax;
            }
            else
            {
                throw new CustomException("获取用户账户异常", HttpStatus.UNAUTHORIZED);
            }
        }
        throw new CustomException("获取用户账户异常", HttpStatus.NOT_FOUND);
    }

    /**
     * 检查是否授权
     */
    @PostMapping("/auth/checkAuthUser")
    public AjaxResult checkAuthUser(SysAuthUser authUser)
    {
        Long userId = SecurityUtils.getLoginUser().getUser().getUserId();
        String source = authUser.getSource();
        if (sysAuthUserService.checkAuthUser(userId, source) > 0)
        {
            return error(source + "平台账号已经绑定");
        }
        return AjaxResult.success();
    }

    /**
     * 取消授权
     */
    @PostMapping("/auth/unlock")
    public AjaxResult unlockAuth(SysAuthUser authUser)
    {
        return toAjax(sysAuthUserService.deleteSysAuthUserById(authUser.getAuthId()));
    }
}
